import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import s from './HostIpView.module.css';

function drawLine(d) {
	const x1 = d.source.x + (d.target.position === 'right' ? 200 : 0);
	const y1 = d.source.y + 10;
	const x2 = d.target.x;
	const y2 = d.target.y;
	const xc = (x1 + x2) / 2;
	const yc = Math.round((y2 - 0) / 2);

	return `M${x1},${y1} C${xc},${y1} ${xc},${yc} ${x2},${y2}`;
}

export default function HostIpView({
	className,
	options,
	data,
	onChangeViewToIpPort,
}) {
	const {
		hostLabelWidth,
		hostLabelHeight,
		labelWidthPadding,
		labelHeightPadding,
	} = options;
	const [active, setActive] = React.useState({
		type: '',
		hostActive: {},
		ipActive: {},
	});

	return (
		<g className={cn(className, s.hostIpView)}>
			<g className={s.links}>
				{data.ipNodeLinks.map(d => (
					<path
						key={`${d.source.name}-${d.target.name}`}
						className={cn(s.line, {
							[s.active]:
								active.hostActive[d.source.name] &&
								active.ipActive[d.target.name],
						})}
						d={drawLine(d)}
					/>
				))}
			</g>
			<g className={s.hostLabels}>
				{data.hosts.map(host => (
					<g
						key={host.name}
						className={cn(s.host, {
							[s.active]: active.hostActive[host.name],
						})}
						onMouseOver={() => {
							const ip = data.hostIpMap[host.name];
							setActive({
								type: 'host',
								hostActive: { [host.name]: true },
								ipActive: ip ? { [ip]: true } : {},
							});
						}}
						onMouseOut={() => {
							setActive({
								type: '',
								hostActive: {},
								ipActive: {},
							});
						}}
					>
						<rect
							x={host.x}
							y={host.y}
							width={hostLabelWidth}
							height={hostLabelHeight}
						/>
						<text
							x={host.x + labelWidthPadding}
							y={host.y + labelHeightPadding}
						>
							{host.name}
						</text>
					</g>
				))}
			</g>
			<g className={s.ipNodes}>
				{data.ips.map(ip => (
					<g
						key={ip.name}
						className={cn(s.ip, {
							[s.active]: active.ipActive[ip.name],
						})}
						transform={`translate(${ip.x},${ip.y})`}
						data-position={`${ip.position}`}
						onMouseOver={() => {
							const hosts = data.ipMap[ip.name]?.hosts;
							if (!hosts || !hosts.size) return;

							setActive({
								type: 'ip',
								hostActive: Array.from(hosts).reduce((obj, x) => {
									obj[x] = true;
									return obj;
								}, {}),
								ipActive: { [ip.name]: true },
							});
						}}
						onMouseOut={() => {
							setActive({
								type: '',
								hostActive: {},
								ipActive: {},
							});
						}}
						onClick={() => onChangeViewToIpPort(ip.name)}
					>
						<circle />
						<text
							dy=".3em"
							dx={ip.position === 'right' ? '.5em' : '-0.5rem'}
							textAnchor={ip.position === 'right' ? 'start' : 'end'}
							transform={`rotate(${
								ip.position === 'left' ? ip.rad - 180 : ip.rad
							})`}
						>
							{ip.name}
						</text>
					</g>
				))}
			</g>
		</g>
	);
}

HostIpView.propTypes = {
	className: PropTypes.string,
	width: PropTypes.number.isRequired,
	height: PropTypes.number.isRequired,
	options: PropTypes.object.isRequired,
	data: PropTypes.object.isRequired,
	onChangeViewToIpPort: PropTypes.func.isRequired,
};

HostIpView.defaultProps = {
	className: s.hostIpView,
};
